﻿using System;
using System.Windows;
using System.Windows.Controls;

namespace FluentTemplates
{
    /// <summary>
    /// A class used for wrapping objects returned from GetTemplateChild operations. 
    /// </summary>
    /// <typeparam name="T">Dependancy Object</typeparam>
    public class TemplatePart<T> where T : DependencyObject
    {

      
        #region C'tors

        public TemplatePart(T obj)
        {
            Object = obj;
        }

        public TemplatePart(T obj, string templatePartName)
        {
            Object = obj;
            TemplatePartName = templatePartName;
        }
        public bool SkipFurtherProcessing { get; set; }
        public Control Control { get; set; }
        public TemplatePart(T obj, string templateName, Control control)
        {
            Object = obj;
            this.TemplatePartName = templateName;
            Control = control;
        }

        #endregion

        #region Instance Properties

        /// <summary>
        /// The wrapped object
        /// </summary>
        public T Object { get; set; }

        public string TemplatePartName { get; set; }

        #endregion

        #region Instance Methods

        /// <summary>
        /// Throws and ArgumentException if the wrapped object is null
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public TemplatePart<T> Required()
        {
            return Required(string.Empty);
        }

        /// <summary>
        /// Throws an ArgumentException with the given message if the wrapped object is null
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="message"></param>
        /// <returns></returns>
        public TemplatePart<T> Required(string message)
        {
            if (Object == null)
                throw !string.IsNullOrWhiteSpace(message)
                          ? new ArgumentException(message)
                          : new ArgumentException(string.Format("The required Template Part was not assigned: {0}",
                                                                TemplatePartName));

            return this;
        }

        /// <summary>
        /// Invokes supplied action with the wrapped object <typeparamref name="T"/> if the object is not null
        /// </summary>
        /// <typeparam name="T">the wrapped object type</typeparam>
        /// <param name="bindingExpression">The action to execute on the wrapped object</param>
        /// <returns></returns>
        public TemplatePart<T> WireUp(Action<T> bindingExpression)
        {
            if (Object != null)
                bindingExpression(Object);

            return this;
        }

        #endregion

        #region Operators

        public static implicit operator T(TemplatePart<T> value)
        {
            return value.Object;
        }

        #endregion
        /// <summary>
        /// Stops further processing of the TemplatePart if the given control is not null
        /// </summary>
        /// <param name="control"></param>
        /// <returns></returns>
        public TemplatePart<T> DependsOn(DependencyObject control)
        {
            if (control == null)
                SkipFurtherProcessing = true;
            return this;
        }
    }
}